package com.googlecode.contests_repo.core.model;


import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;

import com.googlecode.contests_repo.core.users.UserManager;

/**
 * A user of the system.
 * 
 * @author deni, joro
 */
public class User {

	private String login;
	private String password;
	private String confirmPassword;
	private String email;
	
	@JsonProperty("real_name")
	private String realName;
	private String city;
	private String[] organizations;
	private String about;
	
	private Map<String, String> errors;
	
	/**
	 * Creates a new user.
	 */
	public User() {
		login = password = confirmPassword = email = realName = city = about = "";
		organizations = new String[5];
		for (int i = 0; i < organizations.length; i++) {
			organizations[i] = "";
		}
		errors = new HashMap<String, String>();
	}

	/**
	 * Gets the login.
	 * 
	 * @return the login
	 */
	public String getLogin() {
		return login;
	}

	/**
	 * Gets the password of the user.
	 * 
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * Sets the password of the user.
	 * 
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Gets the email of the user.
	 * 
	 * @return the email
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * Sets the email of the user.
	 * 
	 * @param email
	 *            the email to set
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * Gets the real name of the user.
	 * 
	 * @return the realName
	 */
	public String getRealName() {
		return realName;
	}

	/**
	 * Sets the real name of the user.
	 * 
	 * @param realName
	 *            the realName to set
	 */
	public void setRealName(String realName) {
		this.realName = realName;
	}

	/**
	 * Gets the city of the user.
	 * 
	 * @return the city
	 */
	public String getCity() {
		return city;
	}

	/**
	 * Sets the city of the user.
	 * 
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

	/**
	 * Gets the organizations the user belongs to.
	 * 
	 * @return the organizations
	 */
	public String[] getOrganizations() {
		return organizations;
	}

	/**
	 * Sets the organizations the user belongs to.
	 * 
	 * @param organizations
	 *            the organizations to set
	 */
	public void setOrganizations(String[] organizations) {
		this.organizations = organizations;
	}

	/**
	 * Gets the additional information about the user.
	 * 
	 * @return the about
	 */
	public String getAbout() {
		return about;
	}

	/**
 	 * Sets the additional information about the user.
	 * 
	 * @param about
	 *            the about to set
	 */
	public void setAbout(String about) {
		this.about = about;
	}

	/**
	 * Sets the login.
	 * 
	 * @param login
	 *            the login to set
	 */
	public void setLogin(String login) {
		this.login = login;
	}

	/**
	 * Gets the confirmPassword field.
	 * 
	 * @return the confirmPassword
	 */
	@JsonIgnore
	public String getConfirmPassword() {
		return confirmPassword;
	}

	/**
	 * Sets the confirmPassword field.
	 * 
	 * @param confirmPassword
	 *            the confirmPassword to set
	 */
	@JsonIgnore
	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	/**
	 * Validates the user data this object contains.
	 * After calling this method, you may use {@link #getValidationErrors()} and
	 * {@link #getValidationError(String)} to get specific error messages.
	 *  
	 * @return
	 * 		true if this object contains valid user data, false otherwise.
	 */
	@JsonIgnore
	public boolean validate() {
		errors.clear();
		
		validateRequiredField(login, "login", 4);
		validateRequiredField(password, "password", 6);
		validateRequiredField(email, "email", 0);		
		validateRequiredField(realName, "realName", 0);
		
		if (!password.equals(confirmPassword)) {
			errors.put("password", "Passwords don't match.");
		}
		
		if (errors.get("login") == null) {
			if (UserManager.isLoginTaken(login)) {
				errors.put("login", "A user with this login already exists.");
			}
		}
		
		return errors.isEmpty();
	}
	
	@JsonIgnore
	private void validateRequiredField(String value, String fieldName, int minLength) {
		if (value == null || value.isEmpty()) {
			errors.put(fieldName, "This field is mandatory.");
		} else {
			if (value.length() < minLength) {
				errors.put(fieldName, fieldName + " should be at least " + minLength + " characters long.");
			}
		}
	}
	
	/**
	 * Gets all validation errors found during the last validation.
	 * 
	 * @return all validation errors
	 * @see #validate()
	 */
	
	@JsonIgnore
	public Map<String, String> getValidationErrors() {
		return errors;
	}
	
	/**
	 * Gets the validation error related to the specified field, found during the last validation.
	 * 
	 * @param key
	 * 		the field for which related errors should be returned.
	 * @return
	 * 		the validation error related to the given field
	 * 		
	 */
	@JsonIgnore
	public String getValidationError(String key) {
		String errorMsg = errors.get(key);
		return errorMsg != null ? errorMsg : "";
	}
}
